home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d3 / ddjhptxt.arc / ALLEN.LST next >
File List  |  1990-06-05  |  11KB  |  408 lines

  1. LISTING ONE
  2.  
  3. /* points.c    Copyright (c) 1989 by Norton T. Allen */
  4.  
  5. #include "points.h"
  6.  
  7. int nbits(int i) {
  8.   int nb;
  9.  
  10.   for (nb = 0; i != 0; nb++) i >>= 1;
  11.   return(nb);
  12. }
  13.  
  14. static int focus_x, focus_y, focus_width, focus_height;
  15.  
  16. /* zeros in map correspond to x bits, 1's to y bits */
  17. static long int z, map, zlim;
  18. static int tbits, xor_y;
  19.  
  20. void init_points(int left, int top, int width, int height) {
  21.   int nbits_w, nbits_h;
  22.   long int mask;
  23.  
  24.   focus_x = left;
  25.   focus_y = top;
  26.   focus_width = width;
  27.   focus_height = height;
  28.   nbits_w = nbits(focus_width);
  29.   nbits_h = nbits(focus_height);
  30.   tbits = nbits_w + nbits_h;
  31.   xor_y = nbits_w < nbits_h;
  32.   z = 0L;
  33.   zlim = 1L << tbits;
  34.   map = 0L;
  35.   for (mask = 1L; nbits_w || nbits_h; ) {
  36.     if (nbits_w > nbits_h || (nbits_w == nbits_h && xor_y)) {
  37.       nbits_w--;
  38.       mask <<= 1;
  39.     }
  40.     if (nbits_h > 0 &&
  41.         (nbits_h > nbits_w || (nbits_w == nbits_h && !xor_y))) {
  42.       nbits_h--;
  43.       map |= mask;
  44.       mask <<= 1;
  45.     }
  46.   }
  47. }
  48.  
  49. int next_point(int *dx, int *dy) {
  50.   int x, y, n;
  51.   long int m, rz;
  52.  
  53.   for (;;) {
  54.     if (z == zlim) return(1);
  55.     m = map; rz = z; n = tbits;
  56.     x = y = 0;
  57.     while (n-- > 0) {
  58.       if (m & 1) { /* this is a ybit */
  59.         y <<= 1;
  60.         if (rz & 1) y++;
  61.       } else {
  62.         x <<= 1;
  63.         if (rz & 1) x++;
  64.       }
  65.       m >>= 1; rz >>= 1;
  66.     }
  67.     z++;
  68.     if (xor_y) y = x ^ y;
  69.     else x = x ^ y;
  70.     if (x >= focus_width) continue;
  71.     if (y >= focus_height) continue;
  72.     break;
  73.   }
  74.   *dx = x + focus_x;
  75.   *dy = y + focus_y;
  76.   return(0);
  77. }
  78.  
  79.  
  80. LISTING TWO
  81.  
  82. /* mandel.c will handle the actual Mandelbrot set calculations.
  83.    Copyright (c) 1989 by Norton T. Allen */
  84.  
  85. #include "grafix.h"
  86.  
  87. /* This is the aspect ratio calculated on my screen: */
  88. #define ASPECT 0.739
  89.  
  90. static double xscale, yscale, xo, yo;
  91.  
  92. /* set_range() is similar to setcoords() except that it guarantees
  93.    equal x and y scales, taking the aspect ratio into account.
  94.    The axis with the smaller scale is adjust so the specified
  95.    range will be centered on the screen.  Another reason for
  96.    not using setcoords() is that I need the inverse functions
  97.    mapping device coordinates to virtual coordinates.
  98. */
  99. void set_range(double xmin, double ymin, double xmax, double ymax) {
  100.   double delta;
  101.  
  102.   yscale = (ymax-ymin)/vp_height();
  103.   xscale = (xmax-xmin)/vp_width();
  104.   if (yscale*ASPECT > xscale) {
  105.     xscale = yscale*ASPECT;
  106.     delta = (xmin + xscale * vp_width() - xmax)/2.;
  107.     xmin -= delta;
  108.     xmax += delta;
  109.   } else {
  110.     yscale = xscale/ASPECT;
  111.     delta = (ymin + yscale * vp_height() - ymax)/2.;
  112.     ymin -= delta;
  113.     ymax += delta;
  114.   }
  115.   xo = xmin;
  116.   yo = ymin;
  117. } /* ---------------------------------------------------------------- */
  118.  
  119. double vx (int dx)              /* convert device x to virtual x */
  120. {
  121.   return ((double) dx * xscale + xo);
  122. } /* ---------------------------------------------------------------- */
  123.  
  124. double vy (int dy)              /* convert device y to virtual y */
  125. {
  126.   return ((double) dy * yscale + yo);
  127. } /* ---------------------------------------------------------------- */
  128.  
  129. /* Membership in the Mandelbrot set is determined by an
  130.    iterative function.  Given the complex starting
  131.    coordinate C the function is:
  132.                 Z(0) = 0.
  133.                 Z(n+1) = Z(n)^2 + C
  134.    A point is deemed to be in the set if NLOOP iterations fails
  135.    to produce a point with absolute value greater than LIMIT.
  136.    Points within the set are colored black.  Points outside the
  137.    set are colored based on how many iterations passed before
  138.    exceeding LIMIT.  Miriad other schemes are possible.  Other
  139.    values for NLOOP and LIMIT are probably desirable, depending
  140.    on how deep you go.
  141. */
  142. #define NLOOP 100
  143. #define LIMIT 10000.
  144. #define NCOLORS 15
  145.  
  146. int mandel_color(double cx, double cy) {
  147.   int k;
  148.   double zx, zy, zx2, zy2;
  149.  
  150.   zx = zy = 0.;
  151.   for (k = 0; k < NLOOP; k++) {
  152.     zx2 = zx*zx;
  153.     zy2 = zy*zy;
  154.     if (zx2+zy2 > LIMIT) break;
  155.     zy = 2*zx*zy + cy;
  156.     zx = zx2 - zy2 + cx;
  157.   }
  158.   if (k < NLOOP) return((k % NCOLORS)+1);
  159.   return(0);
  160. }
  161.  
  162.  
  163. LISTING THREE
  164.  
  165. /* generate.c    Copyright (c) 1989 by Norton T. Allen */
  166.  
  167. #include <stdio.h>
  168. #include <stdlib.h>
  169. #include <dos.h>
  170. #include "points.h"
  171. #include "grafix.h"
  172.  
  173. /* This structure defines a rectangular box which we can move around the
  174.    screen using the cursor keys.  fbox.on is TRUE if the box is
  175.    currently displayed.  fbox.mode takes the values:
  176.                 0       Not active
  177.                 1       Cursor keys move the whole box
  178.                 2       Cursor keys change box's size
  179. */
  180. struct bx {
  181.   int x, y, dx, dy, on, mode;
  182. } fbox = {300, 160, 50, 40, 0, 0};
  183.  
  184. void flip_box(void) {
  185.   set_write_mode(WM_XOR);
  186.   set_color1(15);
  187.   draw_rect(fbox.x, fbox.y, fbox.dx, fbox.dy);
  188.   set_write_mode(WM_REPLACE);
  189.   fbox.on = !fbox.on;
  190. }
  191.  
  192. void help(void) {
  193.   printf("'Esc' to exit\n");
  194.   printf("?     for this message\n");
  195.   printf("m     to move the focus box.(use cursor keys)\n");
  196.   printf("s     to size the focus box.(use cursor keys)\n");
  197.   printf("f     to focus on the focus area\n");
  198.   printf("z     to zoom in on the focus area\n");
  199.   getch();
  200. }
  201.  
  202. static int dm = 1;      /* How many pixels to move with each cursor step */
  203.  
  204. /* check_box makes sure the new box meets the following requirements:
  205.      1. It isn't off the screen.
  206.      2. It's not smaller then 2 pixels in either dimension
  207.    Check box turns off the old box, but leaves the new box off also;
  208.    menu() will turn it on when there's no more keyboard input.
  209. */
  210. void check_box(struct bx *nb) {
  211.   if (nb->x < 0 || nb->y < 0 ||
  212.       nb->x + nb->dx > vp_width() ||
  213.       nb->y + nb->dy > vp_height() ||
  214.       nb->dx < 2 || nb->dy < 2 ||
  215.       (nb->x == fbox.x && nb->y == fbox.y &&
  216.        nb->dx == fbox.dx && nb->dy == fbox.dy))
  217.     return;
  218.   if (fbox.on) flip_box();
  219.   fbox = *nb;
  220.   fbox.on = 0;
  221. }
  222.  
  223. /* These are scan codes for cursor keys: */
  224. #define EX_UP 72
  225. #define EX_DOWN 80
  226. #define EX_RIGHT 77
  227. #define EX_LEFT 75
  228.  
  229. /* Menu supports the following keys:
  230.     ESC         Exit
  231.     M           suspend calculations and put box on the screen in
  232.                 mode 1 for 'moving'.
  233.     S           As with M, but mode 2 for 'sizing'.
  234.     C           Remove box and continue calculations as before
  235.     F           Focus on boxed region.
  236.     Z           Zoom in on boxed region.
  237.     Cursor keys Move or size box
  238.     0-9         Change step size for cursor keys
  239. */
  240. void menu(void) {
  241.   int c;
  242.   struct bx new_box;
  243.   double xmin, ymin, xmax, ymax;
  244.   for (;;) {
  245.     while (kbhit()) {
  246.       c = getch();
  247.       switch (c) {
  248.         case '\033':
  249.           exit(0);
  250.         case 'c':
  251.         case 'C':
  252.           fbox.mode = 0;
  253.           break;
  254.         case 'm':
  255.         case 'M':
  256.           fbox.mode = 1;
  257.           break;
  258.         case 's':
  259.         case 'S':
  260.           fbox.mode = 2;
  261.           break;
  262.         case 'f': /* Focus on boxed region */
  263.         case 'F':
  264.           if (fbox.mode == 0) break;
  265.           init_points(fbox.x, fbox.y, fbox.dx, fbox.dy);
  266.           fbox.mode = 0;
  267.           break;
  268.         case 'z': /* Zoom in on boxed region */
  269.         case 'Z':
  270.           if (fbox.mode == 0) break;
  271.           xmin = vx(fbox.x);
  272.           ymin = vy(fbox.y+fbox.dy);
  273.           ymax = vy(fbox.y);
  274.           xmax = vx(fbox.x+fbox.dx);
  275.           set_range(xmin, ymin, xmax, ymax);
  276.           init_points(0, 0, vp_width(), vp_height());
  277.           pc_textmode();        /* Kluge to clear screen */
  278.           init_video(EGA);
  279.           fbox.mode = fbox.on = 0;
  280.           break;
  281.         case '1':
  282.         case '2':
  283.         case '3':
  284.         case '4':
  285.         case '5':
  286.         case '6':
  287.         case '7':
  288.         case '8':
  289.         case '9':
  290.           dm = c-'0';
  291.           break;
  292.         case 0:
  293.           c = getch();
  294.           new_box = fbox;
  295.           if (fbox.mode == 1) { /* moving the box */
  296.             switch (c) {
  297.               case EX_UP:
  298.                 new_box.y -= dm;
  299.                 break;
  300.               case EX_DOWN:
  301.                 new_box.y += dm;
  302.                 break;
  303.               case EX_RIGHT:
  304.                 new_box.x += dm;
  305.                 break;
  306.               case EX_LEFT:
  307.                 new_box.x -= dm;
  308.                 break;
  309.               default: break;
  310.             }
  311.           } else if (fbox.mode == 2) {
  312.             switch (c) {
  313.               case EX_UP:
  314.                 new_box.dy -= dm;
  315.                 break;
  316.               case EX_DOWN:
  317.                 new_box.dy += dm;
  318.                 break;
  319.               case EX_RIGHT:
  320.                 new_box.dx += dm;
  321.                 break;
  322.               case EX_LEFT:
  323.                 new_box.dx -= dm;
  324.                 break;
  325.               default: break;
  326.             }
  327.           }
  328.           check_box(&new_box);
  329.           break;
  330.         default:
  331.           break;
  332.       }
  333.     }
  334.     if (fbox.mode == 0) break;
  335.     else if (!fbox.on) flip_box();
  336.   }
  337.   if (fbox.on) flip_box();
  338. }
  339.  
  340. /* Generate cycles through all the pixels, possibly starting over as
  341.    dictated by menu().  Generate never returns.
  342. */
  343. void generate(void) {
  344.   int c, x, y;
  345.   double fx, fy;
  346.  
  347.   for (;;) {
  348.     while (next_point(&x, &y) == 0) {
  349.       fx = vx(x);
  350.       fy = vy(y);
  351.       c = mandel_color(fx, fy);
  352.       set_color1(c);
  353.       draw_point(x, y);
  354.       if (kbhit()) menu();
  355.     }
  356.     menu();
  357.   }
  358. }
  359.  
  360. void main(int argc, char **argv) {
  361.   if (init_video (EGA)) {
  362.     init_points(0, 0, vp_width(), vp_height());
  363.     set_range(-2., -.95, .75, .95);
  364.     generate();
  365.   } else printf("Cannot select graphics mode");
  366. }
  367.  
  368.  
  369. LISTING FOUR
  370.  
  371. /* points.h include file for pixel ordering program. */
  372.  
  373. void init_points(int left, int top, int width, int height);
  374.  
  375. int next_point(int *dx, int *dy);
  376.  
  377. int mandel_color(double cx, double cy);
  378.  
  379. void set_range(double xmin, double ymin, double xmax, double ymax);
  380.  
  381. double vx (int dx);             /* convert device x to virtual x */
  382.  
  383. double vy (int dy);             /* convert device y to virtual y */
  384.  
  385. LISTING FIVE
  386.  
  387. To be included in grafix.h
  388.  
  389. /* Added by Norton Allen */
  390. /* --------------------- */
  391. void set_write_mode(int mode);
  392.  
  393. #define WM_REPLACE 0
  394. #define WM_XOR 0x18
  395.  
  396.  
  397. LISTING SIX
  398.  
  399. /* wmode.c for DDJ grafix library Copyright (c) 1989 by Norton T. Allen */
  400.  
  401. #include <dos.h>
  402. #include "grafix.h"
  403.  
  404. int write_mode = WM_REPLACE;
  405.  
  406. void set_write_mode(int mode) {
  407.   write_mode = mode;
  408. }